#!/usr/bin/python
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
# Copyright (c) 2012, 2013, Oracle and/or it's affiliates.  All rights reserved.
#
#
# gen_components
# A simple script to generate (on stdout), the component.html web page 
# found at: http://userland.us.oracle.com/components.html
#

import getopt
import os
import sys

debug = False

# TPNO string to search for in each .p5m file.
TPNO_str = "com.oracle.info.tpno"

# Hashtable of components with TPNOs keyed by component name.
comp_TPNOs = {}

# Hashtable of RE's, RM's and Teams keyed by component path.
owners = {}

# Initial HTML for the generated web page.
preamble = """
<html>
<head>
    <style type='text/css' media='screen'>
        @import '/css/demo_table.css';
        @import '/css/ColVis.css';
        @import '/css/ColReorder.css';

            tr.even:hover,  tr.even:hover td.sorting_1 ,
            tr.odd:hover,  tr.odd:hover td.sorting_1 {
                            background-color: gold;
            }

    </style>
    <script type='text/javascript' src='js/jquery.js'></script>
    <script type='text/javascript' src='js/jquery.dataTables.js'></script>
    <script type='text/javascript' src='js/ColReorder.js'></script>
    <script type='text/javascript' src='js/ColVis.js'></script>

    <script>
        $(document).ready(function() {
            $('#components').dataTable({
                "sDom": 'C<"clear">Rlfrtip',
                bPaginate: true,
                bFilter: true,
                bSort: true,
                iDisplayLength: -1,
                aLengthMenu: [ [ 10, 50, -1], [ 10, 50, 'All'] ]
            });
        });
    </script>
</head>
<body>

<h1>Userland Components</h1>
<p>
<table align='center' id='components'>
<thead>
<tr>
    <th>Component</th>
    <th>Version</th>
    <th>Gate Path</th>
    <th>Package(s)</th>
    <th>ARC Case(s)</th>
    <th>License(s)</th>
    <th>TPNO</th>
    <th>BugDB</th>
    <th>RE</th>
    <th>RM</th>
    <th>Team</th>
</tr>
</thead>
<tbody>
"""

# Final HTML for the generated web page.
postamble = """
</tr>
</tbody>
</table>
</body>
</html>
"""

# Return a hashtable of RE's, RM's and Teams keyed by component path.
def read_owners(owners_file):
    if debug:
        print >> sys.stderr, "Reading %s" % owners_file
    try:
        fin = open(owners_file, 'r')
        lines = fin.readlines()
        fin.close()
    except:
        if debug:
            print >> sys.stderr, "Unable to read owners file: %s" % owners_file

    owners = {}
    for line in lines:
        line = line[:-1]
        component, re, rm, team = line.split("|")
        owners[component] = [ re, rm, team ]

    return owners

# Return a hashtable of components with TPNOs keyed by component name.
def find_TPNOs(workspace):
    comp_TPNOs = {}
    for directory, _, files in os.walk(workspace + "/components"):
        for filename in files:
            if filename.endswith(".p5m"):
                pathname = os.path.join(directory, filename)
                fin = open(pathname, 'r')
                lines = fin.readlines()
                fin.close()

                for line in lines:
                    line = line.replace("\n", "")
                    n = line.find(TPNO_str)
                    if n != -1:
                        tpno_str = line[n:].split("=")[1]
                        try:
                            # Check that the TPNO is a valid number.
                            tpno = int(tpno_str)
                            if debug:
                                print >> sys.stderr, "TPNO: %s: %s" % \
                                    (directory, tpno_str)
                            comp_TPNOs[directory] = tpno_str
                        except:
                            # Check to see if line end in a "\" character in
                            # which case, it's an attribute rather than an
                            # set name action, so extract it a different way.
                            try:
                                n += len(TPNO_str)+1
                                tpno_str = line[n:].split()[0]
                                # Check that the TPNO is a valid number.
                                tpno = int(tpno_str)
                                if debug:
                                    print >> sys.stderr, "TPNO: %s: %s" % \
                                        (directory, tpno_str)

                                # If it's an attribute, there might be more
                                # than one TPNO for this component.
                                if directory in comp_TPNOs:
                                    entry = comp_TPNOs[directory]
                                    tpno_str = "%s,%s" % (entry, tpno_str)

                                comp_TPNOs[directory] = tpno_str
                            except:
                                print >> sys.stderr, \
                                    "Unable to read TPNO: %s" % pathname

    return(comp_TPNOs)

# Return a sorted list of the directories containing one or more .p5m files.
def find_p5m_dirs(workspace):
    p5m_dirs = []
    for dir, _, files in os.walk(workspace + "/components"):
        for file in files:
            if file.endswith(".p5m"):
                p5m_dirs.append(dir)

    return sorted(list(set(p5m_dirs)))

# Write out the initial HTML for the components.html web page.
def write_preamble():
    print preamble

# Return the RE,  RM and Team for this component.
def get_owner(p5m_dir):
    result = [ "Unknown", "Unknown", "Unknown" ]
    component_path = ""
    started = False
    tokens = p5m_dir.split("/")
    for token in tokens:
        if started:
            component_path += token + "/"
        if token == "components":
            started = True
    component_path = component_path[:-1]
    if component_path in owners:
        result = owners[component_path]
    if debug:
        print >> sys.stderr, "Component path: ", component_path,
        print >> sys.stderr, "RE, RM, Team: ", result
    
    return result

# Generate an HTML table entry for all the information for the component
# in the given directory. This generates a file called 'component-report'
# under the components build directory.
def gen_reports(workspace, component_dir):
    if debug:
        print >> sys.stderr, "Processing %s" % component_dir

    try:
        tpno = comp_TPNOs[component_dir]
    except:
        tpno = ""

    re, rm, team = get_owner(component_dir)
    makefiles = "-f Makefile -f %s/make-rules/component-report" % workspace
    targets = "clean component-hook"
    template = "cd %s; "
    template += "TPNO='%s' "
    template += "RESPONSIBLE_ENGINEER='%s' "
    template += "RESPONSIBLE_MANAGER='%s' "
    template += "TEAM='%s' "
    template += "gmake COMPONENT_HOOK='gmake %s component-report' %s"
    cmd = template % (component_dir, tpno, re, rm, team, makefiles, targets)

    if debug:
        print >> sys.stderr, "gen_reports: command: `%s`" % cmd
    lines = os.popen(cmd).readlines()

# Collect all the .../build/component-report files and write them to stdout.
def write_reports(p5m_dirs, owners_file):
    for p5m_dir in p5m_dirs:
        report = "%s/build/component-report" % p5m_dir
        if debug:
            print >> sys.stderr, "Reading %s" % report
        try:
            fin = open(report, 'r')
            lines = fin.readlines()
            fin.close()
            sys.stdout.writelines(lines)
        except:
            if debug:
                print >> sys.stderr, "Unable to read: %s" % report

# Write out the final HTML for the components.html web page.
def write_postamble():
    print postamble

# Write out a usage message showing valid options to this script.
def usage():
    print  >> sys.stderr, \
"""
Usage: 
      gen-components [OPTION...]

-d, --debug
      Turn on debugging

-o, --owners
      Location of a file containing a list of RE's /RM's per component

-w --workspace
      Location of the Userland workspace
"""

    sys.exit(1)


if __name__ == "__main__":
    workspace = os.getenv('WS_TOP')
    owners_file = "/net/userland.us.oracle.com/gates/private/RE-RM-list.txt"

    try:
        opts, args = getopt.getopt(sys.argv[1:], "do:w:",
            [ "debug", "owners=", "workspace=" ])
    except getopt.GetoptError, err:
        print str(err)
        usage()

    for opt, arg in opts:
        if opt in [ "-d", "--debug" ]:
            debug = True
        elif opt in [ "-o", "--owners" ]:
            owners_file = arg
        elif opt in [ "-w", "--workspace" ]:
            workspace = arg
        else:
            assert False, "unknown option"
 
    owners = read_owners(owners_file)
    write_preamble()
    comp_TPNOs = find_TPNOs(workspace)
    p5m_dirs = find_p5m_dirs(workspace)
    for p5m_dir in p5m_dirs:
        gen_reports(workspace, p5m_dir)
    write_reports(p5m_dirs, owners_file)
    write_postamble()
    sys.exit(0)
